﻿/*------------------------------------------------------------------------

CSMART_ARRAY.HPP v1.4

Copyright 楊志賢 CxxlMan, 2013 - 2014
All Rights Reserved

採用計數器技術，所以不能用於有循環參照的物件。

-------------------------------------------------------------------------*/

#ifndef CSMART_ARRAY_HPP_CxxlMan
#define CSMART_ARRAY_HPP_CxxlMan

#include <CRITICAL.HPP>


namespace CxxlMan
{

template <typename T>
class CSmart_Array
{

  class Bag
  {
    CriticalSec csObject;
    unsigned int Counter; // 記錄 Bag 被放入 CSmart_Array 的計數，當減至 0 時，此 Bag 被解構

    T *m_pArray;  // 包裹的物件陣列
  public:

    // Constructor
    Bag(T *pArray)
    {
      Counter = 1;
      m_pArray = pArray;
    }

    // Destructor
    ~Bag()
    {
      delete [] m_pArray;
    }

    void cxxlFASTCALL IncCounter()
    {
      csObject.Enter();
      ++Counter;
      csObject.Leave();
    }

    // 當減至 0 時陣列應被解構
    bool cxxlFASTCALL DecCounter()
    {
      CriticalSecHandle AutoCSH(csObject);      
      
      if(--Counter == 0)
        return true;
      else
        return false;
    }

    // 用自動轉形方式取得包裹的陣列
    cxxlFASTCALL operator T*()
    {
      return m_pArray;
    }

    bool cxxlFASTCALL isNULL()
    {
      return m_pArray == NULL;
    }

  };

  Bag *m_pBag;

public:
  // Constructor
  CSmart_Array(T *pSrc)
  {
    m_pBag = new Bag(pSrc);
  }

  // Copy Constructor
  CSmart_Array(const CSmart_Array<T> &Src)
  {
    Src.m_pBag->IncCounter();
    m_pBag = Src.m_pBag;
  }

  // Destructor
  virtual ~CSmart_Array()
  {
    if(m_pBag->DecCounter())
      delete m_pBag;
  }

  // 拷備函數
  CSmart_Array<T> & cxxlFASTCALL operator=(const CSmart_Array<T> &Src)
  {
    if(&Src != this)
    {
      Src.m_pBag->IncCounter();
      if(m_pBag->DecCounter())
        delete m_pBag;
      m_pBag = Src.m_pBag;
    }

    return *this;
  }

  // 用自動轉形方式取得包裹的陣列
  cxxlFASTCALL operator T*() const
  {
    return (T *)*m_pBag;
  }

  bool cxxlFASTCALL isNULL()
  {
    return m_pBag->isNULL();
  }

  const T& cxxlFASTCALL operator [](int Index) const
  {
    T *p = *m_pBag;

    return p[Index];
  }

  T& cxxlFASTCALL operator [](int Index)
  {
    T *p = *m_pBag;

    return p[Index];
  }

  // 放棄持有的物件
  void cxxlFASTCALL Destroy()
  {
    if(m_pBag != NULL)
      if(m_pBag->DecCounter())
        delete m_pBag;

    m_pBag = NULL;
  }

};

}  /* namespace CxxlMan */
#endif // CSMART_ARRAY_HPP_CxxlMan
